package cn.iocoder.yudao.module.project.controller.admin.productioncode;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.http.ContentType;
import cn.hutool.poi.word.WordUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.project.controller.admin.internalcode.vo.InternalCodePageReqVO;
import cn.iocoder.yudao.module.project.controller.admin.internalcode.vo.InternalCodeRespVO;
import cn.iocoder.yudao.module.project.controller.admin.internalcode.vo.InternalCodeWorkstationRespVO;
import cn.iocoder.yudao.module.project.controller.admin.kismaterielexwarehouse.vo.CartonCodeDetailNumVO;
import cn.iocoder.yudao.module.project.controller.admin.order.vo.OrderSaveReqVO;
import cn.iocoder.yudao.module.project.controller.admin.weighthistory.vo.WeightHistoryPageReqVO;
import cn.iocoder.yudao.module.project.dal.dataobject.dispatchlist.DispatchListDO;
import cn.iocoder.yudao.module.project.dal.dataobject.internalcode.InternalCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kisbatchcode.KisBatchCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kismaterialreceipt.KisMaterialReceiptDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kismaterielexwarehouse.KisMaterielExWarehouseDO;
import cn.iocoder.yudao.module.project.dal.dataobject.order.OrderDO;
import cn.iocoder.yudao.module.project.dal.dataobject.orderdetail.OrderDetailDO;
import cn.iocoder.yudao.module.project.dal.dataobject.supplier.SupplierDO;
import cn.iocoder.yudao.module.project.dal.dataobject.weighthistory.WeightHistoryDO;
import cn.iocoder.yudao.module.project.dal.mysql.dispatchlist.DispatchListMapper;
import cn.iocoder.yudao.module.project.dal.mysql.internalcode.InternalCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kisbatchcode.KisBatchCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kismaterialreceipt.KisMaterialReceiptMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kismaterielexwarehouse.KisMaterielExWarehouseMapper;
import cn.iocoder.yudao.module.project.dal.mysql.order.OrderMapper;
import cn.iocoder.yudao.module.project.dal.mysql.orderdetail.OrderDetailMapper;
import cn.iocoder.yudao.module.project.dal.mysql.productioncode.ProductionCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.supplier.SupplierMapper;
import cn.iocoder.yudao.module.project.service.internalcode.InternalCodeService;
import cn.iocoder.yudao.module.project.service.kismaterielexwarehouse.KisMaterielExWarehouseService;
import cn.iocoder.yudao.module.project.service.order.OrderService;
import cn.iocoder.yudao.module.project.service.productprocesscompleted.ProductProcessCompletedService;
import cn.iocoder.yudao.module.project.service.weighthistory.WeightHistoryService;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.deepoove.poi.XWPFTemplate;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;

import javax.validation.*;
import javax.servlet.http.*;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;

import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.module.project.config.projectDefine.HTTP_STATUS.*;
import static cn.iocoder.yudao.module.project.config.projectDefine.ORDER_STATUS.*;

import cn.iocoder.yudao.module.project.controller.admin.productioncode.vo.*;
import cn.iocoder.yudao.module.project.dal.dataobject.productioncode.ProductionCodeDO;
import cn.iocoder.yudao.module.project.service.productioncode.ProductionCodeService;

@Tag(name = "管理后台 - 成品码信息")
@RestController
@RequestMapping("/project/production-code")
@Validated
public class ProductionCodeController {

    @Resource
    private ProductionCodeService productionCodeService;

    @Resource
    private ProductionCodeMapper productionCodeMapper;

    @Resource
    private InternalCodeMapper internalCodeMapper;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private KisBatchCodeMapper kisBatchCodeMapper;

    @Resource
    private KisMaterielExWarehouseService kisMaterielExWarehouseService;

    @Resource
    private SupplierMapper supplierMapper;

    @Resource
    private KisMaterialReceiptMapper kisMaterialReceiptMapper;

    @Resource
    private OrderService orderService;

    @Resource
    private InternalCodeService internalCodeService;

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private KisMaterielExWarehouseMapper kisMaterielExWarehouseMapper;

    @Resource
    private DispatchListMapper dispatchListMapper;

    @Resource
    private DictDataApi dictDataApi;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private WeightHistoryService weightHistoryService;

    @PostMapping("/create")
    @Operation(summary = "创建成品码信息")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<String> createProductionCode(@Valid @RequestBody ProductionCodeSaveReqVO createReqVO) {
        return success(productionCodeService.createProductionCode(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新成品码信息")
    // @PreAuthorize("@ss.hasPermission('project:production-code:update')")
    public CommonResult<Boolean> updateProductionCode(@Valid @RequestBody ProductionCodeSaveReqVO updateReqVO) {
        productionCodeService.updateProductionCode(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除成品码信息")
    @Parameter(name = "id", description = "编号", required = true)
    // @PreAuthorize("@ss.hasPermission('project:production-code:delete')")
    public CommonResult<Boolean> deleteProductionCode(@RequestParam("id") String id) {
        productionCodeService.deleteProductionCode(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得成品码信息")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    // @PreAuthorize("@ss.hasPermission('project:production-code:query')")
    public CommonResult<ProductionCodeRespVO> getProductionCode(@RequestParam("id") String id) {
        ProductionCodeDO productionCode = productionCodeService.getProductionCode(id);
        return success(BeanUtils.toBean(productionCode, ProductionCodeRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得成品码信息分页")
    // @PreAuthorize("@ss.hasPermission('project:production-code:query')")
    public CommonResult<PageResult<ProductionCodeRespVO>> getProductionCodePage(@Valid ProductionCodePageReqVO pageReqVO) {
        PageResult<ProductionCodeDO> pageResult = productionCodeService.getProductionCodePage(pageReqVO);
        PageResult<ProductionCodeRespVO> result = BeanUtils.toBean(pageResult, ProductionCodeRespVO.class);
        if (null != result) {
            List<ProductionCodeRespVO> list = result.getList();
            if (CollectionUtil.isNotEmpty(list)) {
                for (ProductionCodeRespVO productionCodeRespVO : list) {
                    LocalDateTime downlineTime = productionCodeRespVO.getDownlineTime();
                    String downlineTimeStr = DateUtil.format(downlineTime, "yyyy-MM-dd HH:mm:ss");
                    productionCodeRespVO.setDownlineTimeStr(downlineTimeStr);
                }
            }
        }
        return success(result);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出成品码信息 Excel")
    // @PreAuthorize("@ss.hasPermission('project:production-code:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportProductionCodeExcel(@Valid ProductionCodePageReqVO pageReqVO,
                                          HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<ProductionCodeDO> list = productionCodeService.getProductionCodePage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "成品码信息.xls", "数据", ProductionCodeRespVO.class,
                BeanUtils.toBean(list, ProductionCodeRespVO.class));
    }




    @PostMapping("/productAssociate")
    @Operation(summary = "成品关联")
    public CommonResult<String> productAssociate(@RequestBody ProductionCodeSaveReqVO createReqVO) {
        // 成品码规则：8位 并防重复
        String id = createReqVO.getId();
        String internalCode = createReqVO.getInternalCode();
        if (StringUtils.isBlank(id)) {
            throw new ServiceException(ERROR_STATUS, "成品码不能为空");
        }
        if (id.length() != 8) {
            throw new ServiceException(ERROR_STATUS, "成品码必须为8位");
        }
        ProductionCodeDO productionCodeDO = productionCodeMapper.selectById(id);
        if (null != productionCodeDO) {
            String boundInternalCode = productionCodeDO.getInternalCode();
            if (!StringUtils.equals(internalCode, boundInternalCode)) {
                throw new ServiceException(ERROR_STATUS, "成品码" + id + "已经绑定了内码" + boundInternalCode);
            }
        }

        QueryWrapper<ProductionCodeDO> productionCodeDOQueryWrapper = new QueryWrapper<>();
        productionCodeDOQueryWrapper.eq("internal_code", internalCode);
        List<ProductionCodeDO> exsitsInternalCodes = productionCodeMapper.selectList(productionCodeDOQueryWrapper);
        if (CollectionUtil.isNotEmpty(exsitsInternalCodes)) {
            String boundPrductCode = exsitsInternalCodes.get(0).getId();
            throw new ServiceException(ERROR_STATUS, "内码" + internalCode + "已经绑定了成品码" + boundPrductCode);
        }

        String nickname = SecurityFrameworkUtils.getLoginUserNickname();
        createReqVO.setOperator(nickname);

        return success(productionCodeService.boxScan(createReqVO));
    }

    @PostMapping("/productDownline")
    @Operation(summary = "成品下线")
    public CommonResult<Boolean> productDownline(@RequestBody ProductionCodeSaveReqVO updateReqVO) {
        // 成品码规则：8位 并防重复
        String id = updateReqVO.getId();
        if (StringUtils.isBlank(id)) {
            throw new ServiceException(ERROR_STATUS, "成品码不能为空");
        }
        if (id.length() != 8) {
            throw new ServiceException(ERROR_STATUS, "成品码必须为8位");
        }

        ProductionCodeDO productionCodeDO = productionCodeMapper.selectById(id);
        if (null == productionCodeDO) {
            throw new ServiceException(ERROR_STATUS, "成品码未关联内码");
        }
        if (null != productionCodeDO) {
            productionCodeDO.setDownlineStatus(1);
        }
        try {
            String nickname = SecurityFrameworkUtils.getLoginUserNickname();
            updateReqVO.setOperator(nickname);
            productionCodeMapper.updateById(productionCodeDO);


        }
        catch (ServiceException serviceException) {
            throw new ServiceException(ERROR_STATUS, serviceException.getMessage());
        }
        catch (Exception e) {

        } finally {

        }

        return success(true);
    }

    @GetMapping("/productQuery")
    @Operation(summary = "成品查询")
    // @PreAuthorize("@ss.hasPermission('project:production-code:query')")
    public CommonResult<ProductionQueryVO> productQuery(@RequestParam("code") String code) {
        ProductionQueryVO productionQueryVO = new ProductionQueryVO();
        if (StringUtils.isBlank(code)) {
            throw new ServiceException(ERROR_STATUS, "未扫码");
        }

        ProductionCodeDO productionCodeDO = productionCodeMapper.selectById(code);
        InternalCodeDO internalCodeDO = internalCodeMapper.selectById(code);

        // 如果是成品码
        if (null != productionCodeDO) {
            // 成品信息
            String productCode = productionCodeDO.getId();
            String internalCode = productionCodeDO.getInternalCode();
            internalCodeDO = internalCodeMapper.selectById(internalCode);
        }
        // 如果是内码
        if (null != internalCodeDO) {
            String internalCode = internalCodeDO.getId();
            String rigidity = internalCodeDO.getRigidity();
            String orderDetailId = internalCodeDO.getOrderDetailId();
            String orderCode = internalCodeDO.getOrderCode();
            productionQueryVO.setInternalCode(internalCode);
            productionQueryVO.setOrderDetailId(orderDetailId);
            productionQueryVO.setOrderCode(orderCode);
            if (StringUtils.isNotBlank(rigidity)) {
                productionQueryVO.setRigidity(rigidity);
            }

            OrderDetailDO orderDetailDO = orderDetailMapper.selectById(orderDetailId);
            if (null != orderDetailDO) {
                String flex = orderDetailDO.getFlex();
                Double len = orderDetailDO.getLen();

                productionQueryVO.setFlex(flex);
                productionQueryVO.setLen(len);

                if (StringUtils.isNotBlank(flex)) {
                    String[] strings = flex.split("-");
                    if (strings.length > 0) {
                        productionQueryVO.setMould(strings[strings.length-1]);
                    }
                }
            }
        }


        return success(productionQueryVO);
    }

    // 该接口作废,流程已经改了,2025.02.26
    @PostMapping("/boxScan")
    @Operation(summary = "下线装箱扫描")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<String> boxScan(@RequestBody ProductionCodeSaveReqVO createReqVO) {
        // 成品码规则：8位 并防重复
        String id = createReqVO.getId();
        String internalCode = createReqVO.getInternalCode();
        if (StringUtils.isBlank(id)) {
            throw new ServiceException(ERROR_STATUS, "成品码不能为空");
        }
        if (id.length() != 8) {
            throw new ServiceException(ERROR_STATUS, "成品码必须为8位");
        }
        ProductionCodeDO productionCodeDO = productionCodeMapper.selectById(id);
        if (null != productionCodeDO) {
            String boundInternalCode = productionCodeDO.getInternalCode();
            if (!StringUtils.equals(internalCode, boundInternalCode)) {
                throw new ServiceException(ERROR_STATUS_EXISTS, "成品码" + id + "已经绑定了内码" + boundInternalCode);
            }
        }

        DictDataRespDTO dictDataRespDTO = dictDataApi.parseDictData("fix_workstation_id", "成品关联工位");
        Integer workstationId = Integer.parseInt(dictDataRespDTO.getValue());

        createReqVO.setAssociatedWorkstationId(workstationId);
        createReqVO.setAssociatedWorkstationUserId(SecurityFrameworkUtils.getLoginUserId().intValue());

        if(internalCodeService.checkScanWorkstation(internalCode, workstationId)){
            throw new ServiceException(ERROR_STATUS_EXISTS, "该内码和工位已扫描，请勿重复操作!");
        }

        internalCodeService.isNextWorkstation(internalCode, workstationId);


        QueryWrapper<ProductionCodeDO> productionCodeDOQueryWrapper = new QueryWrapper<>();
        productionCodeDOQueryWrapper.eq("internal_code", internalCode);
        List<ProductionCodeDO> exsitsInternalCodes = productionCodeMapper.selectList(productionCodeDOQueryWrapper);
        if (CollectionUtil.isNotEmpty(exsitsInternalCodes)) {
            String boundPrductCode = exsitsInternalCodes.get(0).getId();
            throw new ServiceException(ERROR_STATUS, "内码" + internalCode + "已经绑定了成品码" + boundPrductCode);
        }

        try {
            // 如果当前订单状态是"进行中",则将其改成"部分结束"
            InternalCodeDO internalCodeDO = internalCodeMapper.selectById(internalCode);
            if (null == internalCodeDO) {
                throw new ServiceException(ERROR_STATUS, "内码" + internalCode + "不存在");
            }


            String orderCode = internalCodeDO.getOrderCode();
            OrderDO order = orderService.getOrder(orderCode);
            if (null == order) {
                Long count = dispatchListMapper.selectCount(DispatchListDO::getTicketNumber, orderCode);
                if(count == 0){
                    throw new ServiceException(ERROR_STATUS, "订单号" + orderCode + "不存在");
                }

                String nickname = SecurityFrameworkUtils.getLoginUserNickname();
                createReqVO.setOperator(nickname);
                String productCode = productionCodeService.boxScan(createReqVO);
                return success(productCode);
            }

            // 下线前检验,如果对应内码缺少称重/平衡测试/刚性测试,则提示
            Double weight = internalCodeDO.getTestWeight();
            String balance = internalCodeDO.getBalance();
            String rigidity = internalCodeDO.getRigidity();
            if (null == weight) {
                throw new ServiceException(ERROR_STATUS, "内码" + internalCode + "未进行称重");
            }
            if (StringUtils.isBlank(balance)) {
                throw new ServiceException(ERROR_STATUS, "内码" + internalCode + "未进行平衡测试");
            }
            if (StringUtils.isBlank(rigidity)) {
                throw new ServiceException(ERROR_STATUS, "内码" + internalCode + "未进行刚性测试");
            }



            String status = order.getStatus();
            if (StringUtils.equals(status, ORDER_STATUS_2)) {
                OrderSaveReqVO orderSaveReqVO = BeanUtils.toBean(order, OrderSaveReqVO.class);
                orderSaveReqVO.setStatus(ORDER_STATUS_3);
                orderService.updateOrder(orderSaveReqVO);
            }

            String nickname = SecurityFrameworkUtils.getLoginUserNickname();
            createReqVO.setOperator(nickname);
            String productCode = productionCodeService.boxScan(createReqVO);

            Long loginUserId = SecurityFrameworkUtils.getLoginUserId();

            if(loginUserId == null){
                throw new ServiceException(ERROR_STATUS_LOGOUT, "登录信息已失效，请重新登录。");
            }

            stringRedisTemplate.opsForHash().put("CACHE_ORDER_CODE", String.valueOf(loginUserId), internalCodeDO.getOrderCode());

            // 根据订单号查询已出库的产品数量,如果全部已出库,则将订单状态改成已完成
            int totalNum = order.getTotalNum().intValue();
            Map<String, Object> param = new HashMap<>();
            param.put("orderCode", orderCode);
            Integer proDuctNum = productionCodeService.selectProDuctNumByOrderCode(param);
            if (null != proDuctNum && proDuctNum.equals(totalNum)) {
                OrderSaveReqVO orderSaveReqVO = BeanUtils.toBean(order, OrderSaveReqVO.class);
                orderSaveReqVO.setStatus(ORDER_STATUS_1);
                orderService.updateOrder(orderSaveReqVO);
            }

            return success(productCode);
        }
        catch (ServiceException serviceException) {
            throw new ServiceException(ERROR_STATUS, serviceException.getMessage());
        }
        catch (Exception e) {

        } finally {

        }

        return success(productionCodeService.boxScan(createReqVO));



    }

    @GetMapping("/productRetrospect")
    @Operation(summary = "成品追溯报表")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<PageResult<ProductRetrospectVO>> selectProductRetrospect(ReportBO pageReqVO) {
        Map<String, Object> params = new HashMap<>();
        params.put("pageNo", (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());
        params.put("pageSize", pageReqVO.getPageSize());

        String productCode = pageReqVO.getProductCode();
        if (StringUtils.isNotBlank(productCode)) {
            params.put("productCode", productCode);
        }
        String[] dateReq = pageReqVO.getDateReq();
        if(null != dateReq && dateReq.length == 2){
            String startTime = dateReq[0];
            String endTime = dateReq[1];
            params.put("startTime", startTime);
            params.put("endTime", endTime);
        }

        List<ProductRetrospectVO> dataList = productionCodeService.selectProductRetrospect(params);
        Long count = productionCodeService.countProductRetrospect(params);
        PageResult<ProductRetrospectVO> pageResult = new PageResult<>();
        pageResult.setList(dataList);
        pageResult.setTotal(count);
        return success(pageResult);
    }

    @RequestMapping("/defectiveProduct")
    @Operation(summary = "不良品报表")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<PageResult<DefectiveProductVO>> selectDefectiveProduct(@RequestBody ReportBO pageReqVO) {
        Map<String, Object> params = new HashMap<>();
        params.put("pageNo", (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());
        params.put("pageSize", pageReqVO.getPageSize());

        String orderCode = pageReqVO.getOrderCode();
        if (StringUtils.isNotBlank(orderCode)) {
            params.put("orderCode", orderCode);
        }

        String materialCode = pageReqVO.getMaterialCode();
        if (StringUtils.isNotBlank(materialCode)) {
            params.put("materialCode", materialCode);
        }

        String supplierId = pageReqVO.getSupplierId();
        if (StringUtils.isNotBlank(supplierId)) {
            params.put("supplierId", supplierId);
        }

        String batchCode = pageReqVO.getBatchCode();
        if (StringUtils.isNotBlank(batchCode)) {
            params.put("batchCode", batchCode);
        }

        String internalCode = pageReqVO.getInternalCode();
        if (StringUtils.isNotBlank(internalCode)) {
            params.put("internalCode", internalCode);
        }

        String[] dateReq = pageReqVO.getDateReq();
        if (null != dateReq && dateReq.length == 2) {
            String startTime = dateReq[0];
            String endTime = dateReq[1];
            if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
                LocalDateTime startDate = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                LocalDateTime endDate = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                params.put("startDate", startDate);
                params.put("endDate", endDate);
            }
        }
        List<DefectiveProductVO> dataList = productionCodeService.selectDefectiveProduct(params);
        Long count = productionCodeService.countDefectiveProduct(params);
        PageResult<DefectiveProductVO> pageResult = new PageResult<>();
        pageResult.setList(dataList);
        pageResult.setTotal(count);
        return success(pageResult);
    }

    @GetMapping("/materialBatch")
    @Operation(summary = "物料批次报表")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<PageResult<MaterialBatchVO>> selectMaterialBatch(ReportBO pageReqVO) {
        Map<String, Object> params = new HashMap<>();
        params.put("pageNo", (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());
        params.put("pageSize", pageReqVO.getPageSize());
        String materialCode = pageReqVO.getMaterialCode();

        if (StringUtils.isNotBlank(materialCode)) {
            params.put("materialCode", materialCode);
        }

        List<MaterialBatchVO> dataList = productionCodeService.selectMaterialBatch(params);
        Long count = productionCodeService.countMaterialBatch(params);
        PageResult<MaterialBatchVO> pageResult = new PageResult<>();
        pageResult.setList(dataList);
        pageResult.setTotal(count);
        return success(pageResult);
    }

    @RequestMapping("/materialRigidity")
    @Operation(summary = "刚性测试报表")
    public CommonResult<PageResult<DefectiveProductVO>> selectMaterialRigidity(@RequestBody ReportBO pageReqVO) {
        Map<String, Object> params = new HashMap<>();
        params.put("pageNo", (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());
        params.put("pageSize", pageReqVO.getPageSize());

        String materialCode = pageReqVO.getMaterialCode();
        if (StringUtils.isNotBlank(materialCode)) {
            params.put("materialCode", materialCode);
        }

        String internalCode = pageReqVO.getInternalCode();
        if (StringUtils.isNotBlank(internalCode)) {
            params.put("internalCode", internalCode);
        }

        String orderCode = pageReqVO.getOrderCode();
        if (StringUtils.isNotBlank(orderCode)) {
            params.put("orderCode", orderCode);
        }

        String productCode = pageReqVO.getProductCode();
        if (StringUtils.isNotBlank(productCode)) {
            params.put("productCode", productCode);
        }

        String[] dateReq = pageReqVO.getDateReq();
        if (null != dateReq && dateReq.length == 2) {
            String startTime = dateReq[0];
            String endTime = dateReq[1];
            if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
                LocalDateTime startDate = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                LocalDateTime endDate = LocalDateTime.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                params.put("startDate", startDate);
                params.put("endDate", endDate);
            }
        }

        List<DefectiveProductVO> dataList = productionCodeService.selectMaterialRigidity(params);
        Long count = productionCodeService.countMaterialRigidity(params);
        PageResult<DefectiveProductVO> pageResult = new PageResult<>();
        pageResult.setList(dataList);
        pageResult.setTotal(count);
        return success(pageResult);
    }

    @RequestMapping("/materialReceipt")
    @Operation(summary = "入库报表")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<PageResult<MaterialReceiptVO>> selectMaterialReceipt(@RequestBody ReportBO pageReqVO) {
        Map<String, Object> params = new HashMap<>();
        params.put("pageNo", (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());
        params.put("pageSize", pageReqVO.getPageSize());

        String supplierId = pageReqVO.getSupplierId();
        if (StringUtils.isNotBlank(supplierId)) {
            params.put("supplierId", supplierId);
        }

        String batchCode = pageReqVO.getBatchCode();
        if (StringUtils.isNotBlank(batchCode)) {
            params.put("batchCode", batchCode);
        }

        String materialCode = pageReqVO.getMaterialCode();
        if (StringUtils.isNotBlank(materialCode)) {
            params.put("materialCode", materialCode);
        }

        String[] dateReq = pageReqVO.getDateReq();
        if (null != dateReq && dateReq.length == 2) {
            String startTime = dateReq[0];
            String endTime = dateReq[1];
            if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
                LocalDate startDate = LocalDate.parse(startTime);
                LocalDate endDate = LocalDate.parse(endTime);
                params.put("startDate", startDate);
                params.put("endDate", endDate);
            }
        }
        List<MaterialReceiptVO> dataList = productionCodeService.selectMaterialReceipt(params);
        Long count = productionCodeService.countMaterialReceipt(params);

        // 格式化供应商
        if (CollectionUtil.isNotEmpty(dataList)) {
            List<SupplierDO> supplierDOS = supplierMapper.selectList();
            if (CollectionUtil.isNotEmpty(supplierDOS)) {
                for (MaterialReceiptVO kisMaterialReceiptRespVO : dataList) {
                    for (SupplierDO supplierDO : supplierDOS) {
                        String name = supplierDO.getName();
                        if (StringUtils.equals(kisMaterialReceiptRespVO.getSupplierId(), supplierDO.getId())) {
                            kisMaterialReceiptRespVO.setSupplierName(name);
                        }
                    }
                }
            }

        }

        PageResult<MaterialReceiptVO> pageResult = new PageResult<>();
        pageResult.setList(dataList);
        pageResult.setTotal(count);
        return success(pageResult);
    }

    @RequestMapping("/materialDelivery")
    @Operation(summary = "出库报表")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<PageResult<MaterialDeliveryVO>> selectMaterialDelivery(@RequestBody ReportBO pageReqVO) {
        Map<String, Object> params = new HashMap<>();
        params.put("pageNo", (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());
        params.put("pageSize", pageReqVO.getPageSize());

        String orderCode = pageReqVO.getOrderCode();
        if (StringUtils.isNotBlank(orderCode)) {
            params.put("orderCode", orderCode);
        }

        String materialCode = pageReqVO.getMaterialCode();
        if (StringUtils.isNotBlank(materialCode)) {
            params.put("materialCode", materialCode);
        }

        String type = pageReqVO.getType();
        if (StringUtils.isNotBlank(type)) {
            params.put("type", type);
        }

        String supplierId = pageReqVO.getSupplierId();
        if (StringUtils.isNotBlank(supplierId)) {
            params.put("supplierId", supplierId);
        }

        String cartonCode = pageReqVO.getCartonCode();
        if (StringUtils.isNotBlank(cartonCode)) {
            params.put("cartonCode", cartonCode);
        }

        String exCode = pageReqVO.getExCode();
        if (StringUtils.isNotBlank(exCode)) {
            params.put("exCode", exCode);
        }

        String[] dateReq = pageReqVO.getDateReq();
        if (null != dateReq && dateReq.length == 2) {
            String startTime = dateReq[0];
            String endTime = dateReq[1];
            if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)) {
                LocalDate startDate = LocalDate.parse(startTime);
                LocalDate endDate = LocalDate.parse(endTime);
                params.put("startDate", startDate);
                params.put("endDate", endDate);
            }
        }
        List<MaterialDeliveryVO> dataList = productionCodeService.selectMaterialDelivery(params);

        // 格式化供应商
        if (CollectionUtil.isNotEmpty(dataList)) {
            List<SupplierDO> supplierDOS = supplierMapper.selectList();
            if (CollectionUtil.isNotEmpty(supplierDOS)) {
                for (MaterialDeliveryVO data : dataList) {
                    for (SupplierDO supplierDO : supplierDOS) {
                        String name = supplierDO.getName();
                        if (StringUtils.equals(data.getSupplierId(), supplierDO.getId())) {
                            data.setSupplierName(name);
                        }
                    }
                }
            }

        }

        Long count = productionCodeService.countMaterialDelivery(params);
        PageResult<MaterialDeliveryVO> pageResult = new PageResult<>();
        pageResult.setList(dataList);
        pageResult.setTotal(count);
        return success(pageResult);
    }

    @GetMapping("/realtimeProduct")
    @Operation(summary = "实时生产列表")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<List<RealtimeProductVO>> selectRealtimeProduct() {
        List<RealtimeProductVO> realtimeProductVOS = productionCodeService.selectRealtimeProduct();
        return success(realtimeProductVOS);
    }
    @GetMapping("/statistics")
    @Operation(summary = "统计当日入库数量,出库数量,生产数量,不良品数量")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<StatisticsVO> selectStatisticsNum() {
        String now = DateUtil.now();
        StatisticsVO statisticsVO = productionCodeService.selectStatisticsNum(now);
        return success(statisticsVO);
    }

    // @GetMapping("/codeRetrospect")
    // @Operation(summary = "扫码溯源")
    // // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    // public CommonResult<List<CodeRetrospectVO>> selectRetrospectByCode(@RequestParam("code") String code) {
    //     if (StringUtils.isBlank(code)) {
    //         throw new ServiceException(ERROR_STATUS, "未扫码");
    //     }
    //     // 由于不知道属于哪种码,分别去查成品码,内码,生产订单编号,箱码
    //     ProductionCodeDO productionCodeDO = productionCodeMapper.selectById(code);
    //     InternalCodeDO internalCodeDO = internalCodeMapper.selectById(code);
    //     OrderDO orderDO = orderMapper.selectById(code);
    //     KisBatchCodeDO kisBatchCodeDO = kisBatchCodeMapper.selectById(code);
    //     // 如果以上4种码都查不到,则返回提示信息
    //     if (null == productionCodeDO
    //             && null == internalCodeDO
    //             && null == orderDO
    //             && null == kisBatchCodeDO
    //     ) {
    //         throw new ServiceException(ERROR_STATUS, "扫码不存在,请重新扫码");
    //     }
    //
    //     List<CodeRetrospectVO> codeRetrospectVOS = new ArrayList<>();
    //
    //     // 如果是成品码
    //     if (null != productionCodeDO) {
    //         // 成品信息
    //         Map<String, Object> productInfo = new HashMap<>();
    //         String productCode = productionCodeDO.getId();
    //         LocalDateTime downlineTime = productionCodeDO.getDownlineTime();
    //         String operator = productionCodeDO.getOperator();
    //
    //         // CodeRetrospectVO codeRetrospectVO = new CodeRetrospectVO();
    //         productInfo.put("productCode", productCode);
    //         productInfo.put("downlineTime", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(downlineTime));
    //         productInfo.put("operator", operator);
    //         // codeRetrospectVO.setProductInfo(productInfo);
    //         // codeRetrospectVOS.add(codeRetrospectVO);
    //
    //         // 生产订单信息
    //         Map<String, Object> orderInfo = new HashMap<>();
    //         String orderCode = productionCodeDO.getOrderCode();
    //         OrderDO orderDO1 = orderMapper.selectById(orderCode);
    //         LocalDateTime orderDate = orderDO1.getOrderDate();
    //         String operator2 = orderDO1.getOperator();
    //
    //         orderInfo.put("orderCode", orderCode);
    //         orderInfo.put("orderDate", orderDate);
    //         orderInfo.put("operator", operator2);
    //         // codeRetrospectVO.setOrderInfo(orderInfo);
    //
    //         // 测试信息
    //         Map<String, Object> measureInfo = new HashMap<>();
    //         String internalCode = productionCodeDO.getInternalCode();
    //         InternalCodeDO internalCodeDO1 = internalCodeMapper.selectById(internalCode);
    //         Double weight = internalCodeDO1.getWeight();
    //         String rigidity = internalCodeDO1.getRigidity();
    //         String balance = internalCodeDO1.getBalance();
    //         String operator1 = internalCodeDO1.getOperator();
    //         LocalDateTime operatingTime = internalCodeDO1.getOperatingTime();
    //
    //         measureInfo.put("weight", weight);
    //         measureInfo.put("rigidity", rigidity);
    //         measureInfo.put("balance", balance);
    //         measureInfo.put("operatingTime", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(operatingTime));
    //         measureInfo.put("operator", operator1);
    //         // codeRetrospectVO.setMeasureInfo(measureInfo);
    //
    //         // 出库单信息
    //         Map<String, Object> materialDeliveryInfo = new HashMap<>();
    //         String cartonCodes = internalCodeDO1.getCartonCodes();
    //         if (StringUtils.isNotBlank(cartonCodes)) {
    //             Map<String, Object> params = new HashMap<>();
    //             params.put("cartonCodes", cartonCodes);
    //             List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseService.selectMaterialByCartonCodes(params);
    //             if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
    //                 for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOS) {
    //                     String cartonCode = kisMaterielExWarehouseDO.getCartonCode();
    //                     String code1 = kisMaterielExWarehouseDO.getCode();
    //                     String type = kisMaterielExWarehouseDO.getType();
    //                     String operator3 = kisMaterielExWarehouseDO.getOperator();
    //                     LocalDateTime updateTime = kisMaterielExWarehouseDO.getUpdateTime();
    //
    //                     materialDeliveryInfo.put("operator", operator3);
    //                     materialDeliveryInfo.put("deliveryTime", updateTime);
    //                     materialDeliveryInfo.put("cartonCode", cartonCode);
    //
    //                     // 箱码信息
    //                     Map<String, Object> cartonInfo = new HashMap<>();
    //                     KisBatchCodeDO kisBatchCodeDO1 = kisBatchCodeMapper.selectById(cartonCode);
    //                     String supplierId = kisBatchCodeDO1.getSupplierId();
    //                     String batchCode = kisBatchCodeDO1.getBatchCode();
    //                     String materialCode = kisBatchCodeDO1.getMaterialCode();
    //                     String dateStr = kisBatchCodeDO1.getDateStr();
    //                     if (StringUtils.isNotBlank(supplierId)) {
    //                         SupplierDO supplierDO = supplierMapper.selectById(supplierId);
    //                         if (null != supplierDO) {
    //                             String name = supplierDO.getName();
    //                             cartonInfo.put("supplier", name);
    //                             cartonInfo.put("batchCode", batchCode);
    //                             cartonInfo.put("materialCode", materialCode);
    //                         }
    //                     }
    //
    //                     // 入库信息
    //                     Map<String, Object> receiptInfo = new HashMap<>();
    //                     QueryWrapper<KisMaterialReceiptDO> queryWrapper = new QueryWrapper<>();
    //                     queryWrapper.eq("supplier", supplierId);
    //                     queryWrapper.eq("code", batchCode);
    //                     queryWrapper.eq("material_code", materialCode);
    //                     queryWrapper.eq("date_str", dateStr);
    //                     List<KisMaterialReceiptDO> kisMaterialReceiptDOS = kisMaterialReceiptMapper.selectList(queryWrapper);
    //                     if (CollectionUtil.isNotEmpty(kisMaterialReceiptDOS)) {
    //                         KisMaterialReceiptDO kisMaterialReceiptDO = kisMaterialReceiptDOS.get(0);
    //                         String operator4 = kisMaterialReceiptDO.getOperator();
    //                         LocalDateTime receiptDate = kisMaterialReceiptDO.getReceiptDate();
    //                         receiptInfo.put("receiptDate", receiptDate);
    //                         receiptInfo.put("operator", operator4);
    //                     }
    //
    //                     // 整合以上信息
    //                     CodeRetrospectVO codeRetrospectVO = new CodeRetrospectVO();
    //                     codeRetrospectVO.setProductInfo(productInfo);
    //                     codeRetrospectVO.setOrderInfo(orderInfo);
    //                     codeRetrospectVO.setMeasureInfo(measureInfo);
    //                     codeRetrospectVO.setMaterialDeliveryInfo(materialDeliveryInfo);
    //                     codeRetrospectVO.setCartonInfo(cartonInfo);
    //                     codeRetrospectVO.setReceiptInfo(receiptInfo);
    //                     codeRetrospectVOS.add(codeRetrospectVO);
    //                 }
    //             }
    //         }
    //
    //     }
    //     return success(codeRetrospectVOS);
    // }

    @GetMapping("/codeRetrospect")
    @Operation(summary = "扫码溯源")
    // @PreAuthorize("@ss.hasPermission('project:production-code:create')")
    public CommonResult<List<String>> selectRetrospectByCode(@RequestParam("code") String code) {
        if (StringUtils.isBlank(code)) {
            throw new ServiceException(ERROR_STATUS, "未扫码");
        }
        // 由于不知道属于哪种码,分别去查成品码,内码,生产订单编号,箱码
        ProductionCodeDO productionCodeDO = productionCodeMapper.selectById(code);
        InternalCodeDO internalCodeDO;
        if (productionCodeDO != null) {
            internalCodeDO = internalCodeMapper.selectById(productionCodeDO.getInternalCode());
        }else {
            internalCodeDO = internalCodeMapper.selectById(code);
        }

        OrderDO orderDO = orderMapper.selectById(code);
        KisBatchCodeDO kisBatchCodeDO = kisBatchCodeMapper.selectById(code);
        // 如果以上4种码都查不到,则返回提示信息
        if (null == productionCodeDO
                && null == internalCodeDO
                && null == orderDO
                && null == kisBatchCodeDO
        ) {
            throw new ServiceException(ERROR_STATUS, "扫码不存在,请重新扫码");
        }
        if(null == productionCodeDO &&  null != internalCodeDO){
            productionCodeDO= productionCodeMapper.selectOne("internal_Code",code);
        }
        List<String> result = new ArrayList<>();

        // 如果是成品码
        if (null != internalCodeDO) {
            // 成品信息没有
            String productCode ="" ;
            String productMsg  ="";
            if(null != productionCodeDO ){
                productCode = productionCodeDO.getId();
            }

            //    LocalDateTime downlineTime = productionCodeDO.getDownlineTime();
            // 测试信息
            Map<String, Object> measureInfo = new HashMap<>();
            String internalCode = internalCodeDO.getId();
            InternalCodeDO internalCodeDO1 = internalCodeMapper.selectById(internalCode);
            Double weight = internalCodeDO1.getBalanceTwiceWeight();
            String rigidity = internalCodeDO1.getRigidity();
            String balance = internalCodeDO1.getBalance();
            Integer testWorkstationUserId = internalCodeDO1.getTestWorkstationUserId();
            String operator1 = testWorkstationUserId == null ? "" : testWorkstationUserId.toString();
            AdminUserRespDTO adminUserRespDTO = null;
            String operatorTset = "";
            if(StringUtils.isNotBlank(operator1)){
                 adminUserRespDTO = adminUserApi.getUser(Long.valueOf(operator1));
                 operatorTset = adminUserRespDTO.getNickname();
            }

            LocalDateTime operatingTime = internalCodeDO1.getUpdateTime();

            String weightStr = "";
            if (StringUtils.isBlank(rigidity)) {
                rigidity = "暂无";
            }
            if (StringUtils.isBlank(balance)) {
                balance = "暂无";
            }
            if (null == weight) {
                weightStr = "暂无";
            }
            if (null != weight) {
                weightStr = weight + "g";
            }

            measureInfo.put("weight", weight);
            measureInfo.put("rigidity", rigidity);
            measureInfo.put("balance", balance);
            measureInfo.put("operatingTime", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(operatingTime));




            if(null != productionCodeDO ){
                String operator = String.valueOf(internalCodeDO1.getBalanceTwiceWorkstationUserId());
                AdminUserRespDTO operatorProductionUserRespDTO = adminUserApi.getUser(Long.valueOf(operator));

                String operatorProduction = operatorProductionUserRespDTO.getNickname();
                measureInfo.put("operator", operator1);
                productMsg = "成品码 " + productCode + ", 下线时间 "
                        + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(operatingTime)
                        + ", 操作员 " + operatorProduction;
            }


            String measureMsg = "二次称重情况 " + weightStr
                    + ", 刚性测试 " + rigidity
                    + ", 平衡测试 " + balance
                    + ", 操作时间 " + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(operatingTime)
                    + ", 操作员 " + operatorTset;

            String orderCode = internalCodeDO.getOrderCode();
            OrderDO orderDO1 = orderMapper.selectById(orderCode);
            LocalDateTime orderDate =null;
            String operator2 ="";
            String orderDateData  ="";
            if (null != orderDO1) {
                orderDate = orderDO1.getOrderDate();
                operator2 = orderDO1.getOperator();
                orderDateData = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(orderDate);
            }else{
                orderDateData ="";
            }
            String orderMsg = "生产订单 " + orderCode + ", 导入时间 "
                    + orderDateData
                    + ", 操作员 " + operator2;

            String orderDetailId = internalCodeDO1.getOrderDetailId();
            if (StringUtils.isBlank(orderDetailId)) {
                QueryWrapper<InternalCodeDO> internalCodeDOQueryWrapper = new QueryWrapper<>();
                internalCodeDOQueryWrapper.eq("order_code", orderCode);
                internalCodeDOQueryWrapper.last("and (order_detail_id is null or order_detail_id = '')");
                List<InternalCodeDO> internalCodeDOS = internalCodeMapper.selectList(internalCodeDOQueryWrapper);
                List<InternalCodeRespVO> internalCodeRespVOS = BeanUtils.toBean(internalCodeDOS, InternalCodeRespVO.class);
                internalCodeRespVOS = internalCodeService.updateFlex(internalCodeRespVOS);
                internalCodeService.updateOrderDetailId(internalCodeRespVOS);

                internalCodeDO1 = internalCodeMapper.selectById(internalCode);
                orderDetailId = internalCodeDO1.getOrderDetailId();
            }
            if (StringUtils.isNotBlank(orderDetailId)) {
                OrderDetailDO orderDetailDO = orderDetailMapper.selectById(orderDetailId);
                if (null != orderDetailDO) {
                    String flex = orderDetailDO.getFlex();
                    Double len = orderDetailDO.getLen();
                    String drawing = orderDetailDO.getDrawing();
                    orderMsg = "生产订单 " + orderCode
                            + ", 产品规格 " + flex
                            + ", 长度 " + len
                            + ", 图档号 " + drawing
                            + ", 导入时间 "
                            + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(orderDate)
                            + ", 操作员 " + operator2;
                }
            }

            List<String> materialMsgs = new ArrayList<>();

            // 出库单信息
            Map<String, Object> materialDeliveryInfo = new HashMap<>();
            String cartonCodes = internalCodeDO1.getCartonCodes();
            String exCode = internalCodeDO1.getExCode();
            if (StringUtils.isNotBlank(cartonCodes)) {
                // Map<String, Object> params = new HashMap<>();
                // params.put("cartonCodes", cartonCodes);
                // params.put("exCode", exCode);
                // List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseService.selectMaterialByCartonCodes(params);
                QueryWrapper<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOQueryWrapper = new QueryWrapper<>();
                kisMaterielExWarehouseDOQueryWrapper.eq("ex_code", exCode);
                List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectList(kisMaterielExWarehouseDOQueryWrapper);

                if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
                    for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOS) {
                        String cartonCode = kisMaterielExWarehouseDO.getCartonCode();
                        String code1 = kisMaterielExWarehouseDO.getCode();
                        String type = kisMaterielExWarehouseDO.getType();
                        String operator3 = kisMaterielExWarehouseDO.getOperator();
                        LocalDateTime updateTime = kisMaterielExWarehouseDO.getUpdateTime();

                        materialDeliveryInfo.put("operator", operator3);
                        materialDeliveryInfo.put("deliveryTime", updateTime);
                        materialDeliveryInfo.put("cartonCode", cartonCode);

                        String materialDeliveryMsg = "领料时间 "
                                + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(updateTime)
                                + ", 操作员 " + operator3;

                        // 箱码信息
                        Map<String, Object> cartonInfo = new HashMap<>();
                        Iterable<String> items = Splitter.on(',').split(cartonCode);
                        // 循环领料的所有箱码
                        List<String> itemList = Lists.newArrayList(items);
                        for (String item : itemList) {
                            //      System.out.println(item); // Print each item in the list
                            cartonCode = item;
                            KisBatchCodeDO kisBatchCodeDO1 = kisBatchCodeMapper.selectById(cartonCode);
                            String supplierId = kisBatchCodeDO1.getSupplierId();
                            String batchCode = kisBatchCodeDO1.getBatchCode();
                            String materialCode = kisBatchCodeDO1.getMaterialCode();
                            String dateStr = kisBatchCodeDO1.getDateStr();
                            String cartonMsg = "";
                            if (StringUtils.isNotBlank(supplierId)) {
                                SupplierDO supplierDO = supplierMapper.selectById(supplierId);
                                if (null != supplierDO) {
                                    String name = supplierDO.getName();
                                    cartonInfo.put("supplier", name);
                                    cartonInfo.put("batchCode", batchCode);
                                    cartonInfo.put("materialCode", materialCode);

                                    cartonMsg = "供应商 " + name
                                            + ", 批次码 " + batchCode
                                            + ", 物料编号 " + materialCode;

                                }
                            }

                            // 入库信息
                            Map<String, Object> receiptInfo = new HashMap<>();
                            QueryWrapper<KisMaterialReceiptDO> queryWrapper = new QueryWrapper<>();
                            queryWrapper.eq("supplier", supplierId);
                            queryWrapper.eq("code", batchCode);
                            queryWrapper.eq("material_code", materialCode);
                            queryWrapper.eq("date_str", dateStr);
                            String receiptMsg = "";
                            List<KisMaterialReceiptDO> kisMaterialReceiptDOS = kisMaterialReceiptMapper.selectList(queryWrapper);
                            if (CollectionUtil.isNotEmpty(kisMaterialReceiptDOS)) {
                                KisMaterialReceiptDO kisMaterialReceiptDO = kisMaterialReceiptDOS.get(0);
                                String operator4 = kisMaterialReceiptDO.getOperator();
                                LocalDateTime receiptDate = kisMaterialReceiptDO.getReceiptDate();
                                receiptInfo.put("receiptDate", receiptDate);
                                receiptInfo.put("operator", operator4);

                                receiptMsg = "金蝶入库时间 "
                                        + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(receiptDate)
                                        + ", 操作员 " + operator4;

                            }
                            materialMsgs.add(receiptMsg);
                            materialMsgs.add(cartonMsg);
                            materialMsgs.add(materialDeliveryMsg);
                        }

                    }
                }
            }

            result.add(orderMsg);
            if (CollectionUtil.isNotEmpty(materialMsgs)) {
                result.addAll(materialMsgs);
            }
            result.add(measureMsg);
            result.add(productMsg);

            InternalCodePageReqVO pageReqVO = new InternalCodePageReqVO();
            pageReqVO.setPageNo(PageParam.PAGE_SIZE_NONE);
            pageReqVO.setId(internalCode);
            PageResult<InternalCodeWorkstationRespVO> pageResult = internalCodeService.listWorkstationDetail(pageReqVO);

            if(null != pageResult){
                List<InternalCodeWorkstationRespVO> internalCodeWorkstationRespVOList = pageResult.getList();

                if(null != internalCodeWorkstationRespVOList){
                    for (InternalCodeWorkstationRespVO workstationRespVO : internalCodeWorkstationRespVOList){
                        String weightMsg = "订单编号 " + workstationRespVO.getOrderCode()
                                + ",内码 " + workstationRespVO.getInternalCode()
                                + ",规格型号 " + internalCodeDO.getType()
                                + ",工位 " + workstationRespVO.getWorkstationName()
                                + ",数值 " + workstationRespVO.getWorkstationValue()
                                + ",订单规格 " + workstationRespVO.getFlex()
                                + ",长度 " + workstationRespVO.getLen()
                                + ",操作时间 " + workstationRespVO.getOperatorTime();
                        result.add(weightMsg);
                    }
                }
            }

        }
        return success(result);
    }

    @GetMapping("/exportWord")
    @Operation(summary = "扫码溯源-导出word")
    public void exportWordRetrospectByCode(@RequestParam("code") String code, HttpServletResponse response) throws IOException {
        try (PrintWriter writer = response.getWriter()) {
            ClassPathResource classPathResource = new ClassPathResource("/template/追溯报告.txt");
            InputStream inputStream = classPathResource.getInputStream();

            String templateStr = IoUtil.readUtf8(inputStream);

            String productionCode = "";

            ProductionCodeDO productionCodeDO = productionCodeService.getProductionCode(code);
            if(null != productionCodeDO){
                productionCode = code;
            }else{
                productionCodeDO = productionCodeMapper.selectOne("internal_Code",code);
                if(null != productionCodeDO){
                    productionCode = productionCodeDO.getInternalCode();
                }
            }

            CommonResult result = selectRetrospectByCode(code);
            List<String> list = (List<String>)result.getData();


            String reportList = "";
            for(String msg : list){
                reportList += msg + "\n";
            }

            String filename = "追溯报告_" + DateUtil.format(LocalDateTime.now(), DatePattern.NORM_DATE_PATTERN) + ".txt";
            response.setCharacterEncoding("utf-8");

            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()));
            response.setContentType("text/plain");

            templateStr = templateStr.replaceAll("#reportDate#", DateUtil.format(LocalDateTime.now(), DatePattern.NORM_DATE_PATTERN));
            templateStr = templateStr.replaceAll("#productionCode#", productionCode);
            templateStr = templateStr.replaceAll("#reportList#", reportList);

            writer.write(templateStr);

        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException(ERROR_STATUS, "文件导出失败");
        } finally {
            IoUtil.close(response.getWriter());
        }
    }


    @PutMapping("/updateProductionCodeKey")
    @Operation(summary = "更新成品码key")
    public CommonResult<Boolean> updateProductionCodeKey(@Valid @RequestBody UpdatedProductionCodeVO updatedProductionCodeVO) {
        productionCodeService.updateProductionCodeKey(updatedProductionCodeVO);
        return success(true);
    }
}
